home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / GNUUCP_2 / SOURCE / SYSDEP.VMS < prev    next >
Text File  |  1989-07-31  |  14KB  |  723 lines

  1. /*
  2.  * @(#)sysdep.vms 1.4 87/09/29    Copyright 1987 Free Software Foundation, Inc.
  3.  *
  4.  * Copying and use of this program are controlled by the terms of the
  5.  * GNU Emacs General Public License.
  6.  */
  7.  
  8. #ifndef lint
  9. char sysdep_version[] = "@(#)sysdep.vms gnuucp Version hoptoad-1.4";
  10. #endif
  11.  
  12. /*
  13.  * Split out of uuslave.c by John Gilmore, 8 August 1987.
  14.  * re-worked for VMS by Lol Grant 15th. Aug. 1987, Sept. 87
  15.  */
  16.  
  17. #include "uucp.h"
  18. #include "sysdep.h"
  19. #include "includes.h"
  20.  
  21. #define    CONTROL    "user2:[uucp.uuslave]gnuucp.ctl"
  22.  
  23. /*
  24.  * Exported variables
  25.  */
  26. char sysdep_control[] = CONTROL;
  27.  
  28.  
  29. /* Our variables */
  30. struct tt_mode {
  31.     char class, type;
  32.     short width;
  33.     int basic:24;
  34.     char length;
  35.     long extended;
  36. };
  37.  
  38. struct iosb_struct {
  39.     short status, size, terminator, termsize;
  40. };
  41.  
  42. static struct tt_mode ttold, ttraw;
  43. static struct iosb_struct ttiosb;
  44.  
  45. int fdtty;            /* File descriptor for tty line */
  46.  
  47. void sigint();            /* Forward declaration */
  48.  
  49. /*
  50.  * Translation between integer baud rates and VMS baud rates (grumble)
  51.  */
  52. static struct baudtab {
  53.     int baudrate, damn_B_code;
  54. } baudtab[] = {
  55.  
  56.      110, TT$C_BAUD_110,
  57.      150, TT$C_BAUD_150,
  58.      300, TT$C_BAUD_300,
  59.      600, TT$C_BAUD_600,
  60.      1200, TT$C_BAUD_1200,
  61.      1800, TT$C_BAUD_1800,
  62.      2400, TT$C_BAUD_2400,
  63.      4800, TT$C_BAUD_4800,
  64.      9600, TT$C_BAUD_9600,
  65.      19200, TT$C_BAUD_19200
  66. };
  67.  
  68. static int
  69. damn_B(baud)
  70. {
  71.     register struct baudtab *b;
  72.  
  73.     for (b = baudtab; b->baudrate < baud; b++)
  74.     continue;
  75.     if (b->baudrate == baud)
  76.     return b->damn_B_code;
  77.     return 0;
  78. }
  79.  
  80.  
  81. /*
  82.  * Open the serial line for an incoming call.
  83.  * Argument of NULL or empty string means stdin.
  84.  */
  85. int
  86. openline(ttynam, baud)
  87.     char    *ttynam;
  88.     int    baud;
  89. {
  90.     int ontheline;
  91.     int ret, speed;
  92.     struct dsc$descriptor_s tmp;
  93.  
  94.     ontheline = !(ttynam && ttynam[0]);    /* FIXME, this is garbage */
  95.  
  96.     speed = 0;
  97.  
  98.     if (ontheline)
  99.     ttynam = "SYS$OUTPUT";
  100.  
  101.     tmp.dsc$w_length = strlen(ttynam);
  102.     tmp.dsc$a_pointer = ttynam;
  103.     tmp.dsc$b_class = DSC$K_CLASS_S;
  104.     tmp.dsc$b_dtype = DSC$K_DTYPE_T;
  105.  
  106.     if (((ret = sys$alloc(&tmp, 0, 0, 0)) & 1) != 1) {
  107.     exit(0);
  108.     }
  109.     if (((ret = sys$assign(&tmp, &fdtty, 0, 0)) & 1) != 1) {
  110.     DEBUG(0, "Openline: assign %d", ret);
  111.     exit(0);
  112.     }
  113.     ret = sys$qiow(0, fdtty, IO$_SENSEMODE, 0, 0, 0, &ttold,
  114.            sizeof(ttold), 0, 0, 0, 0);
  115.  
  116.     bcopy(&ttold,&ttraw,sizeof(struct tt_mode));
  117.     ttraw.basic |= TT$M_PASSALL;
  118.     ttraw.basic |= TT$M_NOECHO | TT$M_EIGHTBIT;
  119.     ttraw.basic &= ~TT$M_WRAP & ~TT$M_HOSTSYNC & ~TT$M_TTSYNC;
  120.  
  121.     if (!ontheline)
  122.     speed = damn_B(baud);
  123.  
  124.     ret = sys$qiow(0, fdtty, IO$_SETMODE, 0, 0, 0, &ttraw, sizeof(ttraw),
  125.            speed, 0, 0, 0);
  126.  
  127.     return SUCCESS;
  128. /*    signal(SIGINT,sigint); */
  129. }
  130.  
  131.  
  132. /*
  133.  * Open the serial line for an outgoing call.
  134.  */
  135. int
  136. openout(ttynam, baud)
  137. char *ttynam;
  138. int baud;
  139. {
  140.     int ret, speed;
  141.     struct dsc$descriptor_s tmp;
  142.  
  143.     tmp.dsc$w_length = strlen(ttynam);
  144.     tmp.dsc$a_pointer = ttynam;
  145.     tmp.dsc$b_class = DSC$K_CLASS_S;
  146.     tmp.dsc$b_dtype = DSC$K_DTYPE_T;
  147.  
  148.     if (((ret = sys$alloc(&tmp, 0, 0, 0)) & 1) != 1) {
  149.     return -1;
  150.     }
  151.     if (((ret = sys$assign(&tmp, &fdtty, 0, 0)) & 1) != 1) {
  152.     DEBUG(0, "openout: assign %d", ret);
  153.     return -1;
  154.     }
  155.     ret = sys$qiow(0, fdtty, IO$_SENSEMODE, 0, 0, 0, &ttold,
  156.            sizeof(ttold), 0, 0, 0, 0);
  157.  
  158.     bcopy(&ttold,&ttraw,sizeof(struct tt_mode));
  159.  
  160.     ttraw.basic |= TT$M_PASSALL;
  161.     ttraw.basic |= TT$M_NOECHO | TT$M_EIGHTBIT;
  162.     ttraw.basic &= ~TT$M_WRAP & ~TT$M_HOSTSYNC & ~TT$M_TTSYNC;
  163.  
  164.     speed = damn_B(baud);
  165.  
  166.     ret = sys$qiow(0, fdtty, IO$_SETMODE, 0, 0, 0, &ttraw, sizeof(ttraw),
  167.            speed, 0, 0, 0);
  168.  
  169.     signal(SIGINT, sigint);
  170.     return SUCCESS;
  171. }
  172.  
  173.  
  174. /*
  175.  * Basement level I/O routines
  176.  *
  177.  * xwrite() writes a character string to the serial port
  178.  * xgetc() returns a character from the serial port, or an EOF for timeout.
  179.  * sigint() restores the state of the serial port on exit.
  180.  * hangup() hangs up the serial port (e.g. drop DTR).
  181.  */
  182.  
  183. void
  184. sigint()
  185. {
  186.     /* Restore terminal settings on dialout line */
  187.     sys$qiow(0, fdtty, IO$_SETMODE, 0, 0, 0, &ttold, sizeof(ttold),
  188.          0, 0, 0, 0);
  189.     exit(0);
  190. }
  191.  
  192.  
  193.  
  194. /* Nothing is quite as simple in VMS */
  195. xwrite(fd, buf, ctr)
  196. int fd;
  197. char *buf;
  198. int ctr;
  199. {
  200.     int ret;
  201.  
  202.     ret = sys$qiow(0, fd, IO$_WRITEVBLK, 0, 0, 0, buf, ctr, 0, 0, 0, 0);
  203.     if ((ret & SS$_NORMAL) != 1)
  204.     return (0);
  205.     return (ctr);
  206. }
  207.  
  208.  
  209. /*
  210.  * Serial port reading routines 
  211.  */
  212. int
  213. xgetc()
  214. {
  215.     char c;
  216.     long trmmsk[2];
  217.     int ret;
  218.  
  219.     trmmsk[0] = 0;
  220.     trmmsk[1] = 0;
  221.  
  222.     ret = sys$qiow(0, fdtty, IO$_READVBLK | IO$M_TIMED, &ttiosb, 0, 0,
  223.            &c, 1, BYTE_TIMEOUT, trmmsk, 0, 0);
  224.  
  225.     if (ttiosb.status == SS$_TIMEOUT)
  226.     return (EOF);
  227.  
  228.     if (ret & SS$_NORMAL)
  229.     return (c & 0xff);
  230.  
  231.     return (EOF);
  232. }
  233.  
  234. /*
  235.  * hangup(): hang up the 'fone.
  236.  */
  237. int
  238. hangup()
  239. {
  240.     int ret;
  241.  
  242.     xwrite(fdtty, "+++\r", 4);    /* This means disconnect to some modems */
  243. /*
  244.     This is supposed to hang up the modem. but
  245.     causes access violations. It isn't desirable
  246.     for direct connections anyway.
  247.     ret = sys$qiow(0, fdtty, (IO$_SETMODE | IO$M_HANGUP),
  248.         0, 0, 0, 0, 0, 0, 0, 0, 0);
  249. */
  250.     sys$dassgn(fdtty);
  251.     sys$dalloc(0, 0);
  252.     sleep(2);            /* To be sure DTR stays down that long */
  253. }
  254.  
  255.  
  256.  
  257. /*
  258.  * Create a temporary file name for receiving a file into.
  259.  * "name" is the name we will actually eventually want to use for the file.
  260.  * We currently ignore it, but some OS's that can't move files around
  261.  * easily might want to e.g. put the temp file into the same directory
  262.  * that this file is going into.
  263.  *
  264.  * FIXME:
  265.  * This interface should be able to return a "possible" filename, and
  266.  * be re-called if the name is already in use, to get another.
  267.  * This avoids checking here whether the name is good -- saving system calls.
  268.  */
  269. char *
  270. temp_filename(name)
  271. register char *name;
  272. {
  273.     static char tname[NAMESIZE];
  274.  
  275.     if (ourpid == 0)
  276.     ourpid = getpid();
  277.     (void) sprintf(tname, "TM.u%d", ourpid);
  278.     DEBUG(7, "Using temp file %s\n", tname);
  279.     return tname;
  280. }
  281.  
  282.  
  283. /*
  284.  * Transform a filename from a uucp packet (in Unix format) into a local
  285.  * filename that will work in the local file system.
  286.  */
  287. char *
  288. munge_filename(name)
  289. register char *name;
  290. {
  291.     int i, l, j;
  292.     int slash = 0;
  293.     char buff[NAMESIZE+SLOP];
  294.  
  295.     DEBUG(7, "Munge_filename  input: %s\n", name);
  296.     l = strlen(name);
  297.  
  298.     for (i = l; i >= 0; i--)
  299.         if (name[i] == '/') {
  300.         slash++;
  301.             break;
  302.     }
  303.     j = 0;
  304.     for (i++; i < l; i++)
  305.         buff[j++] = name[i];
  306.     buff[j++] = '\0';
  307.     l = strlen(buff);
  308.  
  309.     sprintf(name, "%s%s", slash ? Pubdir : "", buff);
  310.  
  311.     DEBUG(7, "Munge_filename output: %s\n", name);
  312.     return name;
  313. }
  314.  
  315.  
  316. /*
  317.  * Uucp work queue scan.
  318.  *
  319.  * gotsome = work_scan(hostname, type);
  320.  * return 1 if files matching type.hostname* exist.
  321.  * if hostname is NULL, match type.*. Sets up template for work_next.
  322.  *
  323.  * workfile = work_next();
  324.  * Return the name of the next file to match or NULL.
  325.  *
  326.  * void work_done();
  327.  * No more matches required.
  328.  */
  329.  
  330. int context = NULL;        /* Context for lib$find_file */
  331. char template[255];        /* Template for lib$find_file to match */
  332.  
  333. void
  334. work_done()
  335. {
  336.     if (context)
  337.     lib$find_file_end(&context);
  338.     context = NULL;
  339. }
  340.  
  341.  
  342. /* return 1 if type.host* exists else 0 */
  343.  
  344. int
  345. work_scan(host, type)
  346. char *host;
  347. char *type;
  348. {
  349.     int length, ret;
  350.     char *strchr();
  351.     char file_found[255];
  352.     struct dsc$descriptor_s result_dsc, file_dsc;
  353.  
  354.     result_dsc.dsc$w_length = 0;
  355.     result_dsc.dsc$a_pointer = file_found;
  356.     result_dsc.dsc$b_class = DSC$K_CLASS_S;
  357.     result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
  358.  
  359.     file_dsc.dsc$w_length = strlen(template);
  360.     file_dsc.dsc$a_pointer = template;
  361.     file_dsc.dsc$b_class = DSC$K_CLASS_S;
  362.     file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
  363.  
  364.     if (!host)
  365.     host = "";
  366.  
  367.     sprintf(template, "%s.%s*", type, host);
  368.  
  369.     if (context)
  370.     work_done();        /* Clean up prev call, if any */
  371.  
  372.     file_dsc.dsc$w_length = strlen(template);
  373.     result_dsc.dsc$w_length = sizeof(file_found);
  374.  
  375.     ret = lib$find_file(&file_dsc, &result_dsc, &context);
  376.  
  377.     work_done();
  378.  
  379.     switch (ret) {
  380.     case RMS$_NORMAL:
  381.     return 1;
  382.  
  383.     case RMS$_NMF:        /* no more files */
  384.     default:
  385.     return NULL;
  386.     }
  387. }
  388.  
  389.  
  390. char *
  391. work_next()
  392. {
  393.     int length, ret;
  394.     char *strchr();
  395.  
  396.     static char file_found[255];
  397.  
  398.     struct dsc$descriptor_s result_dsc, file_dsc;
  399.  
  400.     result_dsc.dsc$w_length = sizeof(file_found);
  401.     result_dsc.dsc$a_pointer = file_found;
  402.     result_dsc.dsc$b_class = DSC$K_CLASS_S;
  403.     result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
  404.  
  405.     file_dsc.dsc$w_length = strlen(template);
  406.     file_dsc.dsc$a_pointer = template;
  407.     file_dsc.dsc$b_class = DSC$K_CLASS_S;
  408.     file_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
  409.  
  410.     ret = lib$find_file(&file_dsc, &result_dsc, &context);
  411.  
  412.     length = strchr(file_found, ' ') - file_found;
  413.     file_found[length] = '\0';
  414.  
  415.     switch (ret) {
  416.     case RMS$_NORMAL:
  417.     return file_found;
  418.  
  419.     case RMS$_NMF:        /* no more files */
  420.     default:
  421.     return NULL;
  422.     }
  423. }
  424.  
  425. bcopy(from, to, cnt)
  426. register char *from;
  427. register char *to;
  428. register int cnt;
  429. {
  430.     register int i;
  431.  
  432.     for (i = 0; i < cnt; i++)
  433.         *to++ = *from++;
  434. }
  435.  
  436. bzero(s, cnt)
  437. register char *s;
  438. register int cnt;
  439. {
  440.     register int i;
  441.  
  442.     for (i = 0; i < cnt; i++)
  443.         *s++ = '\0';
  444. }
  445.  
  446. rename(from, to)
  447. char *to, *from;
  448. {
  449.     int ifd, ofd, n;
  450.  
  451.     char buff[512];
  452.  
  453.     if ((ifd = open(from, 0)) < 0)
  454.         return (0);
  455.  
  456.     if ((ofd = creat(to, 0)) < 0)
  457.         return (1);
  458.  
  459.     while ((n = read(ifd, buff, sizeof(buff))) > 0)
  460.         write(ofd, buff, n);
  461.     if (close(ifd) < 0)
  462.         return (1);
  463.     if (close(ofd) < 0)
  464.         return (1);
  465.     delete(from);
  466.     return (0);
  467. }
  468.  
  469. char *
  470. strtok(string, separators)
  471. char *string, *separators;
  472. {
  473.     char *p;
  474.     static char *start, *last;
  475.  
  476.     if (string != NULL) {
  477.     start = string;
  478.     /* skip leading separators */
  479.         while(*start && isin(*start,separators))
  480.         start++;
  481.     last = start;
  482.     }
  483.  
  484.     p = start;
  485.  
  486.     if (*last == NULL)
  487.     return NULL;
  488.  
  489.     /* find first separator and NULL it */
  490.     while (*last && !isin(*last, separators))
  491.     last++;
  492.     *last++ = NULL;
  493.  
  494.     /* find next non-separator */
  495.     while (*last && isin(*last, separators))
  496.     last++;
  497.     start = last;
  498.     return p;
  499. }
  500.  
  501. isin(ch, setofchars)
  502. char ch, *setofchars;
  503. {
  504.     char *cp;
  505.  
  506.     for (cp = setofchars; *cp; cp++)
  507.     if (*cp == ch)
  508.         return 1;
  509.     return 0;
  510. }
  511.  
  512. spawn(command, input, output)
  513. char *command, *input, *output;
  514. {
  515.     int ret;
  516.     int status;
  517.  
  518.     $DESCRIPTOR(tmp1, command);
  519.     $DESCRIPTOR(tmp2, input);
  520.     $DESCRIPTOR(tmp3, output);
  521.  
  522.     tmp1.dsc$w_length = strlen(command);
  523.     tmp2.dsc$w_length = strlen(input);
  524.     tmp3.dsc$w_length = strlen(output);
  525.  
  526.     ret = lib$spawn(&tmp1, &tmp2, &tmp3, 0, 0, 0, &status, 0, 0, 0);
  527.     DEBUG(1, "spawn: completed %d\n", ret);
  528.     if (!(ret & 1 && status & 1))
  529.     return (0);
  530.     return (status);
  531. }
  532.  
  533. /*
  534. ** void pqsort(vec, nel, esize, compptr)
  535. **
  536. **  Quick Sort routine.
  537. **  Based on Knuth's ART OF COMPUTER PROGRAMMING, VOL III, pp 114-117.
  538. **  For some unknown reason, this works faster than the library's qsort.
  539. **
  540. ** Parameters:
  541. **  vec = points to beginning of structure to sort.
  542. **  nel = number of elements.
  543. **  esize = size of an element.
  544. **  compptr = points to the routine for comparing two elements.
  545. **
  546. ** Returns:
  547. **  Nothing.
  548. */
  549.  
  550. static int elsize;        /* Element size */
  551. static int (*comp) ();        /* Address of comparison routing */
  552.  
  553. static void memexch(), mysort();
  554.  
  555. void 
  556. pqsort(vec, nel, esize, compptr)
  557. unsigned char *vec;
  558. int nel;
  559. int esize;
  560. int (*compptr) ();
  561.  
  562. {
  563.     /* If less than 2 items, done */
  564.     if (nel < 2)
  565.     return;
  566.  
  567.     elsize = esize;
  568.     comp = compptr;
  569.  
  570.     /* Call the real worker */
  571.     mysort(vec, nel);
  572. }
  573.  
  574. /*
  575. ** void mysort(vec, nel)
  576. **
  577. **  The real quick sort routine.
  578. **
  579. ** Parameters:
  580. **  vec = points to beginning of structure to sort.
  581. **  nel = number of elements.
  582. **
  583. **  esize = size of an element.
  584. **  compptr = points to the routine for comparing two elements.
  585. **
  586. ** Returns:
  587. **  Nothing.
  588. */
  589.  
  590. static void 
  591. mysort(vec, nel)
  592. unsigned char *vec;
  593. int nel;
  594.  
  595. {
  596.     register short i, j;
  597.     register unsigned char *iptr, *jptr, *kptr;
  598.  
  599.     /* * If 2 items, check them by hand. */
  600.  
  601. begin:
  602.     if (nel == 2) {
  603.     if ((*comp) (vec, vec + elsize) > 0)
  604.         memexch(vec, vec + elsize, elsize);
  605.     return;
  606.     }
  607.     /* * Initialize for this round. */
  608.  
  609.     j = nel;
  610.     i = 0;
  611.     kptr = vec;
  612.     iptr = vec;
  613.     jptr = vec + elsize * nel;
  614.  
  615.     while (--j > i) {
  616.  
  617.     /* * From the righthand side, find the first value that should be *
  618.      * to the left of k. */
  619.  
  620.     jptr -= elsize;
  621.     if ((*comp) (jptr, kptr) > 0)
  622.         continue;
  623.  
  624.     /* * Now from the lefthand side, find the first value that should be *
  625.      * to the right of k. */
  626.  
  627.     iptr += elsize;
  628.     while (++i < j && (*comp) (iptr, kptr) <= 0)
  629.         iptr += elsize;
  630.  
  631.     if (i >= j)
  632.         break;
  633.  
  634.     /* * Exchange the two items. * k will eventually end up between them. */
  635.  
  636.     memexch(jptr, iptr, elsize);
  637.     }
  638.  
  639.     /* * Move item 0 into position. */
  640.  
  641.     memexch(vec, iptr, elsize);
  642.  
  643.     /* * Now sort the two partitions. */
  644.  
  645.     if ((nel -= (i + 1)) > 1)
  646.     mysort(iptr + elsize, nel);
  647.  
  648.     /* * To save a little time, just start the routine over by hand. */
  649.  
  650.     if (i > 1) {
  651.     nel = i;
  652.     goto begin;
  653.     }
  654. }
  655.  
  656. /*
  657. ** memexch(s1, s2, n)
  658. **
  659. **  Exchange the contents of two vectors.
  660. **
  661. ** Parameters:
  662. **  s1 = points to one vector.
  663. **  s2 = points to another vector.
  664. **  n = size of the vectors in bytes.
  665. **
  666. ** Returns:
  667. **  Nothing.
  668. */
  669.  
  670. static void 
  671. memexch(s1, s2, n)
  672. register unsigned char *s1;
  673. register unsigned char *s2;
  674. register int n;
  675.  
  676. {
  677.     register unsigned char c;
  678.  
  679.     while (n--) {
  680.     c = *s1;
  681.     *s1++ = *s2;
  682.     *s2++ = c;
  683.     }
  684. }
  685.  
  686. getwd(buff)
  687. char *buff;
  688. {
  689.     char *p = getenv("PATH");
  690.  
  691.     strcpy(buff, p);
  692. }
  693.  
  694. system(buff)
  695. char *buff;
  696. {
  697.     return (spawn(buff, "NL:", "NL:") & 1 == 0);
  698. }
  699.  
  700. /*
  701.  * Routine to return a string that gives the current date and time, and
  702.  * identifies the current process, if on a multiprocess system.
  703.  */
  704. char *
  705. time_and_pid()
  706. {
  707.     long clock;
  708.     struct tm *tm;
  709.     static int ourpid = 0;
  710.     static char format[] = "%d/%d-%d:%02d:%02d-%d";
  711.     static char outbuf[sizeof(format)];
  712.  
  713.     (void) time(&clock);
  714.     tm = localtime(&clock);
  715.     if (ourpid == 0)
  716.         ourpid = getpid();
  717.     sprintf(outbuf, format,
  718.         tm->tm_mon+1, tm->tm_mday,
  719.         tm->tm_hour, tm->tm_min, tm->tm_sec,
  720.         ourpid);
  721.     return outbuf;
  722. }
  723.